use std::{fs::remove_dir_all, process::Command};

use objc::{class, msg_send, runtime::Object, sel, sel_impl};
#[allow(unused_imports)]
use tauri::Manager;
use tauri::{
    menu::{CheckMenuItem, Menu, MenuItem},
    tray::{MouseButton, TrayIconBuilder, TrayIconEvent},
    AppHandle, Emitter, LogicalSize, PhysicalPosition, Position, Size,
};
use tauri_plugin_autostart::{MacosLauncher, ManagerExt};
use tauri_plugin_global_shortcut::{Code, Modifiers, Shortcut};
use tauri_plugin_sql::Migration;

pub mod exec;

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run(migrations: Vec<Migration>) {
    let ctrl_p = Shortcut::new(Some(Modifiers::CONTROL | Modifiers::SHIFT), Code::KeyP);
    tauri::Builder::default()
        .plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
            let _ = show_window(app);
        }))
        .plugin(
            tauri_plugin_global_shortcut::Builder::new()
                .with_shortcut(ctrl_p)
                .unwrap()
                .with_handler(move |app, shortcut, _event| {
                    if shortcut == &ctrl_p {
                        show_search_window(app);
                    }
                })
                .build(),
        )
        .plugin(tauri_plugin_autostart::init(
            MacosLauncher::LaunchAgent,
            None,
        ))
        .plugin(tauri_plugin_os::init())
        .plugin(tauri_plugin_dialog::init())
        .plugin(
            tauri_plugin_sql::Builder::default()
                .add_migrations("sqlite:pro-management.data", migrations)
                .build(),
        )
        .plugin(tauri_plugin_shell::init())
        .setup(|app| {
            // 托盘菜单
            let autostart_manager = app.autolaunch();
            let is_auto = autostart_manager.is_enabled().unwrap_or(false);
            let window = app.get_webview_window("main").unwrap();
            let auto_i =
                CheckMenuItem::with_id(app, "auto", "开机自启", true, is_auto, None::<&str>)?;
            let quit_i = MenuItem::with_id(app, "quit", "退出", true, Some("CmdOrCtrl+Q"))?;
            let menu = Menu::with_items(app, &[&auto_i, &quit_i])?;

            // 开发环境下打开开发者工具
            #[cfg(debug_assertions)]
            window.open_devtools();

            // 托盘图标
            let project_name = app
                .config()
                .product_name
                .as_ref()
                .map(|s| s.clone())
                .unwrap_or_default();
            let _ = TrayIconBuilder::new()
                .icon(app.default_window_icon().unwrap().clone())
                .on_tray_icon_event(|tray, event| match event {
                    TrayIconEvent::Click {
                        button: MouseButton::Left,
                        ..
                    } => {
                        show_window(tray.app_handle());
                    }
                    _ => {}
                })
                .menu(&menu)
                .show_menu_on_left_click(false)
                .tooltip(&project_name)
                .on_menu_event(move |app_handle, event| match event.id.as_ref() {
                    "auto" => {
                        let autostart_manager = app_handle.autolaunch();
                        let is_auto = !(autostart_manager.is_enabled().unwrap_or(false));
                        if is_auto {
                            autostart_manager.enable().unwrap();
                        } else {
                            autostart_manager.disable().unwrap();
                        }
                        auto_i.set_checked(is_auto).unwrap();
                    }
                    "quit" => {
                        app_handle.exit(0);
                    }
                    _ => {}
                })
                .build(app)?;

            #[cfg(target_os = "macos")]
            hide_dock();

            Ok(())
        })
        .on_window_event(|window, event| match event {
            tauri::WindowEvent::CloseRequested { api, .. } => {
                api.prevent_close();
                let _ = window.hide();
            }
            tauri::WindowEvent::Focused(false) => {
                if window.label() == "search" {
                    let _ = window.hide();
                    window.emit("search-hidden", true).unwrap();
                }
            }
            tauri::WindowEvent::Focused(true) => {
                if window.label() == "search" {
                    window.emit("search-hidden", false).unwrap();
                }
            }
            _ => {}
        })
        .invoke_handler(tauri::generate_handler![
            remove,
            hidden_window,
            set_window_height,
            open_with_vscode
        ])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

#[tauri::command]
fn remove(path: &str) -> bool {
    remove_dir_all(path).is_ok()
}

// 如果窗口已经最小化，则恢复窗口
fn show_window(app: &AppHandle) {
    let windows = app.webview_windows();

    let window = windows.values().next().expect("Sorry, no window found");
    if window.is_minimized().unwrap_or_default() {
        let _ = window.unminimize();
    }
    app.get_webview_window("main").unwrap().show().unwrap();
    window.set_focus().expect("设置焦点失败");
}
// 全局快捷键，显示搜索窗口
fn show_search_window(app: &AppHandle) {
    let search_window = app.get_webview_window("search").unwrap();
    let inner_size = search_window.inner_size().unwrap();
    let screen = search_window.current_monitor().unwrap().unwrap();
    let screen_size = screen.size();
    search_window
        .set_position(Position::Physical(PhysicalPosition {
            x: (screen_size.width - inner_size.width) as i32 / 2,
            y: screen_size.height as i32 / 5,
        }))
        .unwrap();
    search_window.show().unwrap();
    search_window.set_focus().expect("设置焦点失败");
}

// 前端调用隐藏窗口
#[tauri::command]
fn hidden_window(app: AppHandle) {
    app.get_webview_window("search").unwrap().hide().unwrap();
}
// 前端调用修改窗口高度
#[tauri::command]
fn set_window_height(app: AppHandle, height: f64) {
    let win = app.get_webview_window("search").unwrap();
    win.set_size(Size::Logical(LogicalSize {
        width: 675.0,
        height,
    }))
    .unwrap();
}
// 在vscode中打开项目
#[tauri::command]
fn open_with_vscode(path: &str) -> Result<(), String> {
    Command::new("open")
        .arg("-a")
        .arg("Visual Studio Code")
        .arg(path)
        .spawn()
        .map_err(|e| format!("{:?},{}", e, path))?;
    Ok(())
}

fn hide_dock() {
    unsafe {
        let app = class!(NSApplication);
        let shared_app: *mut Object = msg_send![app, sharedApplication];
        let _: () = msg_send![shared_app,setActivationPolicy:1];
    }
}
